/**
 * Copyright (c) 2011-2016, James Zhan 詹波 (jfinal@126.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jfinal.config;

import com.jfinal.kit.StrKit;
import com.jfinal.mvc.render.*;

import java.util.HashMap;
import java.util.Map;

/**
 * The constant for JFinal runtime.
 */
final public class Constants {

    private boolean devMode = false;
    private String baseUploadPath = "upload";
    private String baseDownloadPath = "download";
    private String encoding = "UTF-8";
    private String urlParaSeparator = "-";
    private ViewType viewType = ViewType.FREE_MARKER;
    private String jspViewExtension = ".jsp";
    private int maxPostSize = 1024 * 1024 * 10;// 10 Meg
    private int freeMarkerTemplateUpdateDelay = 3600;
    private String freeMarkerViewExtension = ".html";

    private Map<Integer, String> errorViewMapping = new HashMap<Integer, String>();

    public boolean getDevMode() {
        return devMode;
    }

    /**
     * Set development mode.
     * @param devMode the development mode
     */
    public void setDevMode(boolean devMode) {
        this.devMode = devMode;
    }

    public String getEncoding() {
        return encoding;
    }

    /**
     * Set encoding. The default encoding is UTF-8.
     * @param encoding the encoding
     */
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public ViewType getViewType() {
        return viewType;
    }

    /**
     * Set view type. The default value is ViewType.FREE_MARKER
     * Controller.render(String view) will use the view type to render the view.
     * @param viewType the view type
     */
    public void setViewType(ViewType viewType) {
        if (viewType == null) {
            throw new IllegalArgumentException("viewType can not be null");
        }
        if (viewType != ViewType.OTHER) { // setMainRenderFactory will set ViewType.OTHER
            this.viewType = viewType;
        }
    }

    public String getUrlParaSeparator() {
        return urlParaSeparator;
    }

    /**
     * Set urlPara separator. The default value is "-"
     * @param urlParaSeparator the urlPara separator
     */
    public void setUrlParaSeparator(String urlParaSeparator) {
        if (StrKit.isBlank(urlParaSeparator) || urlParaSeparator.contains("/")) {
            throw new IllegalArgumentException("urlParaSepartor can not be blank and can not contains \"/\"");
        }
        this.urlParaSeparator = urlParaSeparator;
    }

    public String getJspViewExtension() {
        return jspViewExtension;
    }

    /**
     * Set Jsp view extension. The default value is ".jsp"
     * @param jspViewExtension the Jsp view extension
     */
    public void setJspViewExtension(String jspViewExtension) {
        this.jspViewExtension = jspViewExtension.startsWith(".") ? jspViewExtension : "." + jspViewExtension;
    }

    /**
     * Set error 404 view.
     * @param error404View the error 404 view
     */
    public void setError404View(String error404View) {
        errorViewMapping.put(404, error404View);
    }

    /**
     * Set error 500 view.
     * @param error500View the error 500 view
     */
    public void setError500View(String error500View) {
        errorViewMapping.put(500, error500View);
    }

    /**
     * Set error 401 view.
     * @param error401View the error 401 view
     */
    public void setError401View(String error401View) {
        errorViewMapping.put(401, error401View);
    }

    /**
     * Set error 403 view.
     * @param error403View the error 403 view
     */
    public void setError403View(String error403View) {
        errorViewMapping.put(403, error403View);
    }

    public void setErrorView(int errorCode, String errorView) {
        errorViewMapping.put(errorCode, errorView);
    }

    public String getErrorView(int errorCode) {
        return errorViewMapping.get(errorCode);
    }

    public String getBaseDownloadPath() {
        return baseDownloadPath;
    }

    /**
     * Set file base download path for Controller.renderFile(...)
     * 设置文件下载基础路径，当路径以 "/" 打头或是以 windows 磁盘盘符打头，
     * 则将路径设置为绝对路径，否则路径将是以应用根路径为基础的相对路径
     * <pre>
     * 例如：
     * 1：参数 "/var/www/download" 为绝对路径，下载文件存放在此路径之下
     * 2：参数 "download" 为相对路径，下载文件存放在 PathKit.getWebRoot() + "/download" 路径之下
     * </pre>
     */
    public void setBaseDownloadPath(String baseDownloadPath) {
        if (StrKit.isBlank(baseDownloadPath)) {
            throw new IllegalArgumentException("baseDownloadPath can not be blank.");
        }
        this.baseDownloadPath = baseDownloadPath;
    }

    public String getBaseUploadPath() {
        return baseUploadPath;
    }

    /**
     * Set file base upload path.
     * 设置文件上传保存基础路径，当路径以 "/" 打头或是以 windows 磁盘盘符打头，
     * 则将路径设置为绝对路径，否则路径将是以应用根路径为基础的相对路径
     * <pre>
     * 例如：
     * 1：参数 "/var/www/upload" 为绝对路径，上传文件将保存到此路径之下
     * 2：参数 "upload" 为相对路径，上传文件将保存到 PathKit.getWebRoot() + "/upload" 路径之下
     * </pre>
     */
    public void setBaseUploadPath(String baseUploadPath) {
        if (StrKit.isBlank(baseUploadPath)) {
            throw new IllegalArgumentException("baseUploadPath can not be blank.");
        }
        this.baseUploadPath = baseUploadPath;
    }

    public int getMaxPostSize() {
        return maxPostSize;
    }

    /**
     * Set max size of http post. The upload file size depend on this value.
     */
    public void setMaxPostSize(int maxPostSize) {
        this.maxPostSize = maxPostSize;
    }

    /**
     * Set the base path for all views
     */
    public void setBaseViewPath(String baseViewPath) {
        Routes.setBaseViewPath(baseViewPath);
    }

    /**
     * Set the mainRenderFactory then your can use your custom render in controller as render(String).
     */
    public void setMainRenderFactory(IMainRenderFactory mainRenderFactory) {
        if (mainRenderFactory == null) {
            throw new IllegalArgumentException("mainRenderFactory can not be null.");
        }
        this.viewType = ViewType.OTHER;
        RenderFactory.me().setMainRenderFactory(mainRenderFactory);
    }

    public void setErrorRenderFactory(IErrorRenderFactory errorRenderFactory) {
        if (errorRenderFactory == null) {
            throw new IllegalArgumentException("errorRenderFactory can not be null.");
        }
        RenderFactory.me().setErrorRenderFactory(errorRenderFactory);
    }

    public void setXmlRenderFactory(IXmlRenderFactory xmlRenderFactory) {
        if (xmlRenderFactory == null) {
            throw new IllegalArgumentException("xmlRenderFactory can not be null.");
        }
        RenderFactory.me().setXmlRenderFactory(xmlRenderFactory);
    }

    public int getFreeMarkerTemplateUpdateDelay() {
        return freeMarkerTemplateUpdateDelay;
    }

    public String getFreeMarkerViewExtension() {
        return freeMarkerViewExtension;
    }
}
